#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
上证指数与美元指数关系分析程序
"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from scipy import stats
import seaborn as sns
from matplotlib.font_manager import FontProperties

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体为黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像时负号'-'显示为方块的问题

def load_data(file_path, encoding='utf-8'):
    """
    加载CSV数据文件
    """
    df = pd.read_csv(file_path, encoding=encoding)
    
    # 转换日期列为日期时间类型
    df['日期'] = pd.to_datetime(df['日期'], format='%Y-%m-%d')
    
    # 处理收盘价、开盘价、高、低 - 移除逗号并转换为浮点数
    for col in ['收盘', '开盘', '高', '低']:
        if col in df.columns:
            # 检查列是否为字符串类型，如果是，则移除逗号
            if df[col].dtype == 'object':  # 'object' dtype typically means strings in pandas
                df[col] = df[col].str.replace(',', '').astype(float)
            # 如果已经是数值类型，就直接确保它是float类型
            else:
                df[col] = df[col].astype(float)
    
    # 处理涨跌幅 - 移除百分号并转换为浮点数
    if '涨跌幅' in df.columns:
        if df['涨跌幅'].dtype == 'object':  # Check if it's string
            df['涨跌幅'] = df['涨跌幅'].str.replace('%', '').astype(float) / 100
        else:
            df['涨跌幅'] = df['涨跌幅'].astype(float) / 100
    
    # 按日期升序排序
    df.sort_values('日期', inplace=True)
    
    return df

def analyze_correlation(sh_index, usd_index):
    """
    分析上证指数和美元指数的相关性
    """
    # 合并数据集，基于日期
    merged_df = pd.merge(sh_index[['日期', '收盘']], 
                         usd_index[['日期', '收盘']], 
                         on='日期', 
                         how='inner', 
                         suffixes=('_上证', '_美元'))
    
    # 计算皮尔逊相关系数
    correlation = merged_df['收盘_上证'].corr(merged_df['收盘_美元'])
    
    # 计算滚动相关性 (60天窗口)
    merged_df['60天滚动相关性'] = merged_df['收盘_上证'].rolling(window=60).corr(merged_df['收盘_美元'])
    
    # 计算变化率相关性
    merged_df['上证变化率'] = merged_df['收盘_上证'].pct_change()
    merged_df['美元变化率'] = merged_df['收盘_美元'].pct_change()
    change_correlation = merged_df['上证变化率'].corr(merged_df['美元变化率'])
    
    return merged_df, correlation, change_correlation

def create_visualizations(merged_df, sh_index, usd_index, correlation, change_correlation):
    """
    创建可视化图表
    """
    # 创建一个包含多个子图的图形
    fig = plt.figure(figsize=(20, 24))
    
    # 1. 时间序列图 - 上证指数和美元指数
    ax1 = plt.subplot(4, 1, 1)
    ax1.plot(sh_index['日期'], sh_index['收盘'], 'r-', label='上证指数')
    ax1.set_xlabel('日期')
    ax1.set_ylabel('上证指数', color='r')
    ax1.tick_params(axis='y', labelcolor='r')
    ax1.set_title('上证指数与美元指数时间序列对比')
    
    # 创建第二个Y轴
    ax2 = ax1.twinx()
    ax2.plot(usd_index['日期'], usd_index['收盘'], 'b-', label='美元指数')
    ax2.set_ylabel('美元指数', color='b')
    ax2.tick_params(axis='y', labelcolor='b')
    
    # 添加图例
    lines1, labels1 = ax1.get_legend_handles_labels()
    lines2, labels2 = ax2.get_legend_handles_labels()
    ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left')
    
    # 格式化x轴日期
    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y/%m'))
    plt.xticks(rotation=45)
    
    # 2. 散点图和回归线
    ax3 = plt.subplot(4, 1, 2)
    sns.regplot(x='收盘_美元', y='收盘_上证', data=merged_df, ax=ax3, scatter_kws={'alpha':0.5})
    ax3.set_title(f'上证指数与美元指数散点图及回归线 (相关系数: {correlation:.3f})')
    ax3.set_xlabel('美元指数收盘价')
    ax3.set_ylabel('上证指数收盘价')
    
    # 3. 变化率散点图
    ax4 = plt.subplot(4, 1, 3)
    sns.regplot(x='美元变化率', y='上证变化率', data=merged_df.dropna(), ax=ax4, scatter_kws={'alpha':0.5})
    ax4.set_title(f'上证指数与美元指数日变化率散点图 (相关系数: {change_correlation:.3f})')
    ax4.set_xlabel('美元指数日变化率')
    ax4.set_ylabel('上证指数日变化率')
    
    # 4. 60天滚动相关性
    ax5 = plt.subplot(4, 1, 4)
    ax5.plot(merged_df['日期'][60:], merged_df['60天滚动相关性'][60:], 'g-')
    ax5.axhline(y=0, color='r', linestyle='--', alpha=0.3)
    ax5.set_title('上证指数与美元指数60天滚动相关性')
    ax5.set_xlabel('日期')
    ax5.set_ylabel('相关系数')
    ax5.xaxis.set_major_formatter(mdates.DateFormatter('%Y/%m'))
    plt.xticks(rotation=45)
    
    plt.tight_layout()
    plt.savefig('上证指数与美元指数关系分析.png', dpi=300)
    
    # 5. 移动平均线分析
    fig2 = plt.figure(figsize=(20, 10))
    
    # 上证指数移动平均线
    sh_index['收盘_MA30'] = sh_index['收盘'].rolling(window=30).mean()
    sh_index['收盘_MA60'] = sh_index['收盘'].rolling(window=60).mean()
    
    ax6 = plt.subplot(2, 1, 1)
    ax6.plot(sh_index['日期'], sh_index['收盘'], 'b-', label='上证指数收盘价')
    ax6.plot(sh_index['日期'], sh_index['收盘_MA30'], 'r-', label='30日移动平均线')
    ax6.plot(sh_index['日期'], sh_index['收盘_MA60'], 'g-', label='60日移动平均线')
    ax6.set_title('上证指数与移动平均线')
    ax6.set_xlabel('日期')
    ax6.set_ylabel('指数值')
    ax6.legend()
    ax6.xaxis.set_major_formatter(mdates.DateFormatter('%Y/%m'))
    plt.xticks(rotation=45)
    
    # 美元指数移动平均线
    usd_index['收盘_MA30'] = usd_index['收盘'].rolling(window=30).mean()
    usd_index['收盘_MA60'] = usd_index['收盘'].rolling(window=60).mean()
    
    ax7 = plt.subplot(2, 1, 2)
    ax7.plot(usd_index['日期'], usd_index['收盘'], 'b-', label='美元指数收盘价')
    ax7.plot(usd_index['日期'], usd_index['收盘_MA30'], 'r-', label='30日移动平均线')
    ax7.plot(usd_index['日期'], usd_index['收盘_MA60'], 'g-', label='60日移动平均线')
    ax7.set_title('美元指数与移动平均线')
    ax7.set_xlabel('日期')
    ax7.set_ylabel('指数值')
    ax7.legend()
    ax7.xaxis.set_major_formatter(mdates.DateFormatter('%Y/%m'))
    plt.xticks(rotation=45)
    
    plt.tight_layout()
    plt.savefig('上证指数与美元指数移动平均线分析.png', dpi=300)
    
    return fig, fig2

def analyze_yearly_correlation(merged_df):
    """
    按年度分析相关性
    """
    merged_df['年份'] = merged_df['日期'].dt.year
    yearly_corr = {}
    
    for year in merged_df['年份'].unique():
        year_data = merged_df[merged_df['年份'] == year]
        yearly_corr[year] = {
            '收盘价相关性': year_data['收盘_上证'].corr(year_data['收盘_美元']),
            '变化率相关性': year_data['上证变化率'].corr(year_data['美元变化率']),
        }
    
    return yearly_corr

def generate_report(correlation, change_correlation, yearly_corr, merged_df):
    """
    生成分析报告
    """
    report = """
# 上证指数与美元指数关系分析报告

## 总体相关性分析

在分析期间（{start_date}至{end_date}），上证指数与美元指数的总体相关系数为{correlation:.4f}。
这表明两者之间存在{corr_strength}的{corr_direction}相关关系。

日变化率的相关系数为{change_correlation:.4f}，表明两个指数的日变动之间存在{change_corr_strength}的{change_corr_direction}相关关系。

## 年度相关性分析

年度相关性分析显示，上证指数与美元指数的关系在不同年份有所不同：

""".format(
        start_date=merged_df['日期'].min().strftime('%Y年%m月%d日'),
        end_date=merged_df['日期'].max().strftime('%Y年%m月%d日'),
        correlation=correlation,
        corr_strength='强' if abs(correlation) > 0.5 else '中等' if abs(correlation) > 0.3 else '弱',
        corr_direction='正' if correlation > 0 else '负',
        change_correlation=change_correlation,
        change_corr_strength='强' if abs(change_correlation) > 0.5 else '中等' if abs(change_correlation) > 0.3 else '弱',
        change_corr_direction='正' if change_correlation > 0 else '负'
    )
    
    # 添加年度相关性分析
    for year, corr_data in yearly_corr.items():
        report += """
### {year}年

- 收盘价相关系数: {price_corr:.4f} ({price_corr_direction}相关)
- 日变化率相关系数: {change_corr:.4f} ({change_corr_direction}相关)

""".format(
            year=year,
            price_corr=corr_data['收盘价相关性'],
            price_corr_direction='正' if corr_data['收盘价相关性'] > 0 else '负',
            change_corr=corr_data['变化率相关性'],
            change_corr_direction='正' if corr_data['变化率相关性'] > 0 else '负'
        )
    
    # 添加趋势分析
    report += """
## 趋势分析

60天滚动相关性分析显示，上证指数与美元指数的相关关系在分析期间内有所波动，这表明两者之间的关系受到多种因素的影响，并非保持恒定。

### 主要观察结果：

1. **总体关系**：整体来看，上证指数与美元指数之间{overall_relation}。

2. **波动特征**：当美元指数上升时，上证指数{sh_behavior_on_usd_rise}；当美元指数下降时，上证指数{sh_behavior_on_usd_fall}。

3. **关键转折点**：在相关性出现显著变化的时期，可能与重大经济事件或政策变化相关。

## 结论与投资启示

1. **分散投资**：鉴于上证指数与美元指数之间的关系特征，投资者可考虑分散投资于受不同货币影响的资产类别。

2. **风险管理**：了解上证指数与美元指数之间的相关性变化，有助于投资者更好地管理风险。

3. **长期视角**：尽管短期内两个指数的关系可能波动，长期投资决策应考虑更全面的宏观经济因素。

本分析仅供参考，投资决策应考虑个人风险承受能力和更广泛的市场因素。

""".format(
        overall_relation='表现出了一定程度的相关性，但关系不稳定' if abs(correlation) < 0.3 else 
                        f'存在明显的{"正" if correlation > 0 else "负"}相关关系',
        sh_behavior_on_usd_rise='通常表现出下跌趋势' if correlation < 0 else '通常也会上升',
        sh_behavior_on_usd_fall='通常表现出上升趋势' if correlation < 0 else '通常也会下跌'
    )
    
    with open('上证指数与美元指数关系分析报告.md', 'w', encoding='utf-8') as f:
        f.write(report)
    
    return report

def main():
    """
    主函数
    """
    # 加载数据
    print("正在加载上证指数数据...")
    sh_index = load_data('上证指数历史数据 .csv')
    
    print("正在加载美元指数数据...")
    usd_index = load_data('美元指数历史数据.csv')
    
    print("正在分析数据相关性...")
    merged_df, correlation, change_correlation = analyze_correlation(sh_index, usd_index)
    
    print("正在进行年度相关性分析...")
    yearly_corr = analyze_yearly_correlation(merged_df)
    
    print("正在生成可视化图表...")
    create_visualizations(merged_df, sh_index, usd_index, correlation, change_correlation)
    
    print("正在生成分析报告...")
    report = generate_report(correlation, change_correlation, yearly_corr, merged_df)
    
    print("\n分析完成！已生成以下文件：")
    print("- 上证指数与美元指数关系分析.png")
    print("- 上证指数与美元指数移动平均线分析.png")
    print("- 上证指数与美元指数关系分析报告.md")
    
    print("\n报告摘要：")
    print("上证指数与美元指数之间的总体相关系数为{:.4f}".format(correlation))
    print("上证指数与美元指数之间的日变化率相关系数为{:.4f}".format(change_correlation))
    
if __name__ == "__main__":
    main()